{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"accelerator":"GPU","colab":{"authorship_tag":"ABX9TyOuzENxctn49HNjNmnJOE11","gpuType":"T4","include_colab_link":true,"provenance":[]},"kaggle":{"accelerator":"gpu","dataSources":[],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<a href=\"https://colab.research.google.com/github/amrzhd/EEGNet/blob/main/EEGNet.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>","metadata":{"colab_type":"text","id":"view-in-github"}},{"cell_type":"markdown","source":"# Motor Imagery Task Classification\n","metadata":{"id":"x_5wKiVyBTzL"}},{"cell_type":"markdown","source":"# Extracting Data","metadata":{"id":"O-3Lg9veBge0"}},{"cell_type":"markdown","source":"## Downloading BCI Competition IV 2a Dataset","metadata":{"id":"W4JrI64nBl52"}},{"cell_type":"code","source":"!wget https://www.bbci.de/competition/download/competition_iv/BCICIV_2a_gdf.zip","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"_6jNZi8rBNjN","outputId":"88ac3846-5abc-411f-93f2-f4e96daeed4e","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:33:06.819137Z","iopub.execute_input":"2025-05-06T05:33:06.819386Z","iopub.status.idle":"2025-05-06T05:33:42.157650Z","shell.execute_reply.started":"2025-05-06T05:33:06.819361Z","shell.execute_reply":"2025-05-06T05:33:42.156993Z"}},"outputs":[{"name":"stdout","text":"--2025-05-06 05:33:06--  https://www.bbci.de/competition/download/competition_iv/BCICIV_2a_gdf.zip\nResolving www.bbci.de (www.bbci.de)... 130.149.80.149\nConnecting to www.bbci.de (www.bbci.de)|130.149.80.149|:443... connected.\nHTTP request sent, awaiting response... 200 OK\nLength: 439968864 (420M) [application/zip]\nSaving to: ‘BCICIV_2a_gdf.zip’\n\nBCICIV_2a_gdf.zip   100%[===================>] 419.59M  13.4MB/s    in 34s     \n\n2025-05-06 05:33:42 (12.4 MB/s) - ‘BCICIV_2a_gdf.zip’ saved [439968864/439968864]\n\n","output_type":"stream"}],"execution_count":1},{"cell_type":"code","source":"!mkdir -p data/cleaned_data/","metadata":{"id":"5DbydQswB27q","vscode":{"languageId":"bat"},"trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:33:42.159252Z","iopub.execute_input":"2025-05-06T05:33:42.159512Z","iopub.status.idle":"2025-05-06T05:33:42.276322Z","shell.execute_reply.started":"2025-05-06T05:33:42.159492Z","shell.execute_reply":"2025-05-06T05:33:42.275589Z"}},"outputs":[],"execution_count":2},{"cell_type":"code","source":"%%capture\n!unzip BCICIV_2a_gdf.zip -d data/raw_data","metadata":{"id":"50hgj12yB54U","vscode":{"languageId":"powershell"},"trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:33:42.277112Z","iopub.execute_input":"2025-05-06T05:33:42.277306Z","iopub.status.idle":"2025-05-06T05:33:48.861758Z","shell.execute_reply.started":"2025-05-06T05:33:42.277284Z","shell.execute_reply":"2025-05-06T05:33:48.860805Z"}},"outputs":[],"execution_count":3},{"cell_type":"markdown","source":"#Installing Packages","metadata":{"id":"Y_mkff9aB-9w"}},{"cell_type":"code","source":"%%capture\n!pip install mne","metadata":{"id":"mqHVmwYyCBsB","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:33:48.862982Z","iopub.execute_input":"2025-05-06T05:33:48.863802Z","iopub.status.idle":"2025-05-06T05:33:52.556104Z","shell.execute_reply.started":"2025-05-06T05:33:48.863772Z","shell.execute_reply":"2025-05-06T05:33:52.555100Z"}},"outputs":[],"execution_count":4},{"cell_type":"code","source":"%%capture\n!pip install torch-summary","metadata":{"id":"ueJFbf8KCCPw","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:33:52.558630Z","iopub.execute_input":"2025-05-06T05:33:52.558939Z","iopub.status.idle":"2025-05-06T05:33:55.571901Z","shell.execute_reply.started":"2025-05-06T05:33:52.558908Z","shell.execute_reply":"2025-05-06T05:33:55.571125Z"}},"outputs":[],"execution_count":5},{"cell_type":"markdown","source":"#Libraries Used","metadata":{"id":"crxgIV9ICD2T"}},{"cell_type":"code","source":"import os\nimport mne\nimport math\nimport copy\n# import gdown\nimport random\nimport scipy.io\nimport numpy as np\nimport pandas as pd\nimport seaborn as sn\nimport matplotlib.pyplot as plt\n\n# Torch\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torchsummary import summary\nfrom torch.autograd import Variable\nfrom torch.utils.data import DataLoader, TensorDataset, random_split\n\n# Scikit-Learn\nfrom sklearn.feature_selection import mutual_info_classif\nfrom sklearn.metrics import confusion_matrix, accuracy_score\nfrom sklearn.model_selection import train_test_split","metadata":{"id":"CEp96MytCGei","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:33:55.572793Z","iopub.execute_input":"2025-05-06T05:33:55.573009Z","iopub.status.idle":"2025-05-06T05:34:02.234374Z","shell.execute_reply.started":"2025-05-06T05:33:55.572985Z","shell.execute_reply":"2025-05-06T05:34:02.233801Z"}},"outputs":[],"execution_count":6},{"cell_type":"markdown","source":"# Building Dataset","metadata":{"id":"nn8IHP2_CQbH"}},{"cell_type":"code","source":"!mkdir -p data/cleaned_data/first_session","metadata":{"id":"JFtUH89-G48b","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:02.235090Z","iopub.execute_input":"2025-05-06T05:34:02.235446Z","iopub.status.idle":"2025-05-06T05:34:02.367263Z","shell.execute_reply.started":"2025-05-06T05:34:02.235427Z","shell.execute_reply":"2025-05-06T05:34:02.366227Z"}},"outputs":[],"execution_count":7},{"cell_type":"markdown","source":"##First Session","metadata":{"id":"f6Bmm_acGc4g"}},{"cell_type":"code","source":"raw_data_folder = 'data/raw_data/'\ncleaned_data_folder = 'data/cleaned_data/first_session/'\nfiles = os.listdir(raw_data_folder)\n\n# Selecting files with suffix 'T.gdf'\nfiltered_files = [file for file in files if file.endswith('T.gdf')]\n\nraw_list = []\n\n# Iterating through filtered files \n'''\n    使用MNE处理EEG数据\n    1.去眼动(EOG)噪声\n    2.滤波\n    3.去基线漂移\n'''\nfor file in filtered_files:\n    file_path = os.path.join(raw_data_folder, file)\n\n    # Reading raw data\n    raw = mne.io.read_raw_gdf(file_path, eog=['EOG-left', 'EOG-central', 'EOG-right'], preload=True)\n    # Droping EOG channels ['EOG-left', 'EOG-central', 'EOG-right']\n    #### 1.implement your code here \n    raw.drop_channels(['EOG-left', 'EOG-central', 'EOG-right'])\n\n    # High Pass Filtering 4-40 Hz\n    #### 2.implement your code here  \n    raw.filter(l_freq=4, h_freq=40, method='iir')\n    # Notch filter for Removal of Line Voltage\n\n    #### 3.implement your code here  \n    raw.notch_filter(freqs=50)\n    # Saving the modified raw data to a file with .fif suffix\n    new_file_path = os.path.join(cleaned_data_folder, file[:-4] + '.fif')\n    raw.save(new_file_path, overwrite=True)\n    # Appending data to the list\n    raw_list.append(raw)\n\nfinal_raw = mne.concatenate_raws(raw_list)\nnew_file_path = os.path.join(cleaned_data_folder, 'First_Session_Subjects.fif')\nfinal_raw.save(new_file_path, overwrite=True)\n","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"X6ViqHGaCUWY","outputId":"39111580-ee4e-4543-f906-f9de7e97d6c7","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:02.368402Z","iopub.execute_input":"2025-05-06T05:34:02.368648Z","iopub.status.idle":"2025-05-06T05:34:28.257204Z","shell.execute_reply.started":"2025-05-06T05:34:02.368624Z","shell.execute_reply":"2025-05-06T05:34:28.256449Z"}},"outputs":[{"name":"stdout","text":"Extracting EDF parameters from /kaggle/working/data/raw_data/A08T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Reading 0 ... 675269  =      0.000 ...  2701.076 secs...\nFiltering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A08T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A08T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A08T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A04T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 600914  =      0.000 ...  2403.656 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A04T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A04T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A04T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A06T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 678979  =      0.000 ...  2715.916 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A06T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A06T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A06T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A09T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 673327  =      0.000 ...  2693.308 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A09T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A09T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A09T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A03T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 660529  =      0.000 ...  2642.116 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A03T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A03T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A03T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A07T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 681070  =      0.000 ...  2724.280 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A07T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A07T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A07T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A01T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 672527  =      0.000 ...  2690.108 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A01T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A01T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A01T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A05T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 686119  =      0.000 ...  2744.476 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A05T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A05T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A05T.fif\n[done]\nExtracting EDF parameters from /kaggle/working/data/raw_data/A02T.gdf...\nGDF file detected\nSetting channel info structure...\nCould not determine channel type of the following channels, they will be set as EEG:\nEEG-Fz, EEG, EEG, EEG, EEG, EEG, EEG, EEG-C3, EEG, EEG-Cz, EEG, EEG-C4, EEG, EEG, EEG, EEG, EEG, EEG, EEG, EEG-Pz, EEG, EEG\nCreating raw.info structure...\nReading 0 ... 677168  =      0.000 ...  2708.672 secs...\n","output_type":"stream"},{"name":"stderr","text":"/usr/lib/python3.11/contextlib.py:144: RuntimeWarning: Channel names are not unique, found duplicates for: {'EEG'}. Applying running numbers for duplicates.\n  next(self.gen)\n","output_type":"stream"},{"name":"stdout","text":"Filtering raw data in 1 contiguous segment\nSetting up band-pass filter from 4 - 40 Hz\n\nIIR filter parameters\n---------------------\nButterworth bandpass zero-phase (two-pass forward and reverse) non-causal filter:\n- Filter order 16 (effective, after forward-backward)\n- Cutoffs at 4.00, 40.00 Hz: -6.02, -6.02 dB\n\nFiltering raw data in 1 contiguous segment\nSetting up band-stop filter from 49 - 51 Hz\n\nFIR filter parameters\n---------------------\nDesigning a one-pass, zero-phase, non-causal bandstop filter:\n- Windowed time-domain design (firwin) method\n- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation\n- Lower passband edge: 49.38\n- Lower transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 49.12 Hz)\n- Upper passband edge: 50.62 Hz\n- Upper transition bandwidth: 0.50 Hz (-6 dB cutoff frequency: 50.88 Hz)\n- Filter length: 1651 samples (6.604 s)\n\nWriting /kaggle/working/data/cleaned_data/first_session/A02T.fif\n","output_type":"stream"},{"name":"stderr","text":"[Parallel(n_jobs=1)]: Done  17 tasks      | elapsed:    0.3s\n/tmp/ipykernel_31/911265343.py:35: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/A02T.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/A02T.fif\n[done]\nWriting /kaggle/working/data/cleaned_data/first_session/First_Session_Subjects.fif\n","output_type":"stream"},{"name":"stderr","text":"/tmp/ipykernel_31/911265343.py:41: RuntimeWarning: This filename (/kaggle/working/data/cleaned_data/first_session/First_Session_Subjects.fif) does not conform to MNE naming conventions. All raw files should end with raw.fif, raw_sss.fif, raw_tsss.fif, _meg.fif, _eeg.fif, _ieeg.fif, raw.fif.gz, raw_sss.fif.gz, raw_tsss.fif.gz, _meg.fif.gz, _eeg.fif.gz or _ieeg.fif.gz\n  final_raw.save(new_file_path, overwrite=True)\n","output_type":"stream"},{"name":"stdout","text":"Closing /kaggle/working/data/cleaned_data/first_session/First_Session_Subjects.fif\n[done]\n","output_type":"stream"},{"execution_count":8,"output_type":"execute_result","data":{"text/plain":"[PosixPath('/kaggle/working/data/cleaned_data/first_session/First_Session_Subjects.fif')]"},"metadata":{}}],"execution_count":8},{"cell_type":"markdown","source":"**List of the events**  \n'1023': 1 Rejected trial  \n'1072': 2 Eye movements  \n'276': 3 Idling EEG (eyes open)  \n'277': 4 Idling EEG (eyes closed)  \n'32766': 5 Start of a new run  \n'768': 6 Start of a trial  \n'769': 7 Cue onset **Left** (class 1) : 0  \n'770': 8 Cue onset **Right** (class 2) : 1  \n'771': 9 Cue onset **Foot** (class 3) : 2  \n'772': 10 Cue onset **Tongue** (class 4): 3","metadata":{"id":"wNqq3V3rCiPn"}},{"cell_type":"code","source":"events = mne.events_from_annotations(final_raw)\nevents[1]","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"-9RZjQbWCoc0","outputId":"fbbd728f-9f7f-457e-d4c9-eaefe67bafa1","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:28.258100Z","iopub.execute_input":"2025-05-06T05:34:28.258572Z","iopub.status.idle":"2025-05-06T05:34:28.351969Z","shell.execute_reply.started":"2025-05-06T05:34:28.258552Z","shell.execute_reply":"2025-05-06T05:34:28.351113Z"}},"outputs":[{"name":"stdout","text":"Used Annotations descriptions: ['1023', '1072', '276', '277', '32766', '768', '769', '770', '771', '772']\n","output_type":"stream"},{"execution_count":9,"output_type":"execute_result","data":{"text/plain":"{'1023': 1,\n '1072': 2,\n '276': 3,\n '277': 4,\n '32766': 5,\n '768': 6,\n '769': 7,\n '770': 8,\n '771': 9,\n '772': 10}"},"metadata":{}}],"execution_count":9},{"cell_type":"markdown","source":"**Time choice:**  \n[0.s, 4s] Post Cue on set:  [2s, 6s]","metadata":{"id":"PJAI_olujhxI"}},{"cell_type":"code","source":"epochs = mne.Epochs(final_raw, events[0], event_id=[7, 8, 9, 10], tmin=0, tmax=4, reject=None, baseline=None, preload=True)\n# 读取epochs中的数据和标签\n### implement your code here \nfirst_session_data = epochs.get_data(copy=True)\nfirst_session_labels = epochs.events[:, -1]","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"OaAuA1mQCqcP","outputId":"4d33fb54-48f8-4eb9-c516-1b97747e39d6","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:28.353097Z","iopub.execute_input":"2025-05-06T05:34:28.353423Z","iopub.status.idle":"2025-05-06T05:34:29.220581Z","shell.execute_reply.started":"2025-05-06T05:34:28.353395Z","shell.execute_reply":"2025-05-06T05:34:29.219793Z"}},"outputs":[{"name":"stdout","text":"Not setting metadata\n2592 matching events found\nNo baseline correction applied\n0 projection items activated\nUsing data from preloaded Raw for 2592 events and 1001 original time points ...\n0 bad epochs dropped\n","output_type":"stream"}],"execution_count":10},{"cell_type":"code","source":"print(\"First_session_dataset shape:\",first_session_data.shape)","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"rVNRjQbfCs3-","outputId":"041d64ef-2b44-49e8-d554-90bc0992bc36","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:29.221467Z","iopub.execute_input":"2025-05-06T05:34:29.221729Z","iopub.status.idle":"2025-05-06T05:34:29.226210Z","shell.execute_reply.started":"2025-05-06T05:34:29.221705Z","shell.execute_reply":"2025-05-06T05:34:29.225472Z"}},"outputs":[{"name":"stdout","text":"First_session_dataset shape: (2592, 22, 1001)\n","output_type":"stream"}],"execution_count":11},{"cell_type":"markdown","source":"###Structuring Data","metadata":{"id":"nA0Hr5BMPE5e"}},{"cell_type":"code","source":"# Choosing Device\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Loss Function classification tasks\n#### 5.implement your code here  \ncriterion = nn.CrossEntropyLoss()\n# Normalizing Labels to [0, 1, 2, 3]\ny_train = first_session_labels - np.min(first_session_labels)\n\n# Normalizing Input features: z-score(mean=0, std=1)\nX_first_session = (first_session_data - np.mean(first_session_data)) / np.std(first_session_data)\n\nX = X_first_session\ny = y_train\n\n# Spliting  Data: 90% for Train and 10% for Test\n#### 6.implement your code here  #### \nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=42, stratify=y)\n\n# Converting to Tensor\nX_train = torch.Tensor(X_train).unsqueeze(1).to(device)\nX_test = torch.Tensor(X_test).unsqueeze(1).to(device)\ny_train = torch.LongTensor(y_train).to(device)\ny_test = torch.LongTensor(y_test).to(device)\n\n# Creating Tensor Dataset\n#### 7.implement your code here  \ntrain_dataset = TensorDataset(X_train, y_train)\ntest_dataset = TensorDataset(X_test, y_test)\n\n# Printing the sizes\nprint(\"Size of X_train:\", X_train.size())\nprint(\"Size of X_test:\", X_test.size())\nprint(\"Size of y_train:\", y_train.size())\nprint(\"Size of y_test:\", y_test.size())\n","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"D5dF6ZydC2PP","outputId":"67fafc85-ff3d-48f3-f08a-3abc663df0b3","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:29.226842Z","iopub.execute_input":"2025-05-06T05:34:29.227005Z","iopub.status.idle":"2025-05-06T05:34:30.136567Z","shell.execute_reply.started":"2025-05-06T05:34:29.226992Z","shell.execute_reply":"2025-05-06T05:34:30.135851Z"}},"outputs":[{"name":"stdout","text":"Size of X_train: torch.Size([2332, 1, 22, 1001])\nSize of X_test: torch.Size([260, 1, 22, 1001])\nSize of y_train: torch.Size([2332])\nSize of y_test: torch.Size([260])\n","output_type":"stream"}],"execution_count":12},{"cell_type":"markdown","source":"#Training Class","metadata":{"id":"xyXDZiZ4E4a_"}},{"cell_type":"code","source":"class TrainModel():\n    def __init__(self,):\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n    def train_model(self, model, train_dataset, learning_rate=0.001, batch_size=64, epochs=500):\n\n        model = model.to(self.device)\n        criterion = nn.CrossEntropyLoss()\n        optimizer = optim.Adam(model.parameters(), lr=learning_rate)\n        train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n        highest_train_accuracy = 0.0\n \n        highest_train_accuracy = 0.0\n\n        for epoch in range(epochs):\n            model.train()\n            running_loss = 0.0\n            correct = 0\n            total = 0\n            for inputs, labels in train_loader:\n                inputs = inputs.to(self.device)\n                labels = labels.to(self.device)\n\n                #### 8.implement your code here model/criterion/optimizer/data_loader\n                optimizer.zero_grad()\n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n                loss.backward()\n                optimizer.step()\n                \n                running_loss += loss.item() * inputs.size(0)\n                _, predicted = torch.max(outputs, 1)\n                total += labels.size(0)\n                correct += (predicted == labels).sum().item()\n\n            epoch_loss = running_loss / len(train_loader.dataset)\n            epoch_accuracy = correct / total\n            if epoch_accuracy > highest_train_accuracy:\n                highest_train_accuracy = epoch_accuracy\n            print(f\"Epoch {epoch+1}/{epochs}, Loss: {epoch_loss:.4f}, Accuracy: {(epoch_accuracy*100):.2f}%\")\n\n        average_loss = running_loss / len(train_loader.dataset)\n        print(\"Average Loss:\", average_loss)\n        print(\"Highest Train Accuracy:\", highest_train_accuracy)\n\n        # Saving model\n        torch.save(model.state_dict(), 'eegnet_model.pth')\n        return model\n","metadata":{"id":"F3nUwuQHE8Hi","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:30.137414Z","iopub.execute_input":"2025-05-06T05:34:30.138008Z","iopub.status.idle":"2025-05-06T05:34:30.145547Z","shell.execute_reply.started":"2025-05-06T05:34:30.137982Z","shell.execute_reply":"2025-05-06T05:34:30.144833Z"}},"outputs":[],"execution_count":13},{"cell_type":"markdown","source":"#Evaluating Model","metadata":{"id":"ObMKFBTxFLBJ"}},{"cell_type":"code","source":"class EvalModel():\n    def __init__(self, model):\n        self.model = model.to(device)\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    def test_model(self, test_dataset):\n        self.model.eval()\n        correct = 0\n        total = 0\n        test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)\n\n        with torch.no_grad():\n            for inputs, labels in test_loader:\n                inputs = inputs.to(self.device)\n                labels = labels.to(self.device)\n                outputs = self.model(inputs)\n                _, predicted = torch.max(outputs.data, 1)\n                #### 9.implement your code here 计算准确率\n                total += labels.size(0)\n                correct += (predicted == labels).sum().item()\n   \n\n        accuracy = (correct / total) * 100\n        print(\"/------------------------------/\")\n        print(f\"Test Accuracy: {accuracy:.2f}%\")\n        print(\"/------------------------------/\")\n        return accuracy\n\n    def plot_confusion_matrix(self, test_dataset, classes):\n        self.model.eval()\n        y_pred = []\n        y_true = []\n        test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)\n\n        with torch.no_grad():\n            for inputs, labels in test_loader:\n                inputs = inputs.to(self.device)\n                labels = labels.to(self.device)\n                outputs = self.model(inputs)\n                _, predicted = torch.max(outputs.data, 1)\n                y_pred.append(predicted.item())\n                y_true.append(labels.item())\n\n        cf_matrix = confusion_matrix(y_true, y_pred)\n        cf_matrix = cf_matrix.astype('float') / cf_matrix.sum(axis=1)[:, np.newaxis]\n\n        df_cm = pd.DataFrame(cf_matrix, index=classes, columns=classes)\n\n        plt.figure(figsize=(10, 7))\n        sn.heatmap(df_cm, annot=True, cmap='Blues', fmt='.2f')\n        plt.xlabel('Predicted labels')\n        plt.ylabel('True labels')\n        plt.title('Confusion Matrix')\n        plt.savefig('confusion_matrix_model.png')\n        plt.show()\n","metadata":{"id":"GxVYOQ_YFM4b","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:30.147835Z","iopub.execute_input":"2025-05-06T05:34:30.148043Z","iopub.status.idle":"2025-05-06T05:34:30.161716Z","shell.execute_reply.started":"2025-05-06T05:34:30.148027Z","shell.execute_reply":"2025-05-06T05:34:30.161088Z"}},"outputs":[],"execution_count":14},{"cell_type":"markdown","source":"#EEGNet Model","metadata":{"id":"vR2z57zqC5iS"}},{"cell_type":"code","source":"class EEGNetModel(nn.Module): # EEGNET-8,2\n    def __init__(self, chans=22, classes=4, time_points=1001, temp_kernel=32,\n                 f1=16, f2=32, d=2, pk1=8, pk2=16, dropout_rate=0.5, max_norm1=1, max_norm2=0.25):\n        super(EEGNetModel, self).__init__()\n        # Calculating FC input features\n        linear_size = (time_points//(pk1*pk2))*f2\n\n        # Temporal Filters\n        self.block1 = nn.Sequential(\n            nn.Conv2d(1, f1, (1, temp_kernel), padding='same', bias=False),\n            nn.BatchNorm2d(f1),\n        )\n        # Spatial Filters\n        self.block2 = nn.Sequential(\n            nn.Conv2d(f1, d * f1, (chans, 1), groups=f1, bias=False), # Depthwise Conv\n            nn.BatchNorm2d(d * f1),\n            nn.ELU(),\n            nn.AvgPool2d((1, pk1)),\n            nn.Dropout(dropout_rate)\n        )\n        self.block3 = nn.Sequential(\n            nn.Conv2d(d * f1, f2, (1, 16),  groups=f2, bias=False, padding='same'), # Separable Conv\n            nn.Conv2d(f2, f2, kernel_size=1, bias=False), # Pointwise Conv\n            nn.BatchNorm2d(f2),\n            nn.ELU(),\n            nn.AvgPool2d((1, pk2)),\n            nn.Dropout(dropout_rate)\n        )\n        self.flatten = nn.Flatten()\n        self.fc = nn.Linear(linear_size, classes)\n\n        # Apply max_norm constraint to the depthwise layer in block2\n        self._apply_max_norm(self.block2[0], max_norm1)\n\n        # Apply max_norm constraint to the linear layer\n        self._apply_max_norm(self.fc, max_norm2)\n\n    def _apply_max_norm(self, layer, max_norm):\n        for name, param in layer.named_parameters():\n            if 'weight' in name:\n                param.data = torch.renorm(param.data, p=2, dim=0, maxnorm=max_norm)\n\n    def forward(self, x):\n         #### 10.implement your code here \n        '''\n            完成forward操作\n            提示：注意输入输出的tensor维度关系\n        '''\n        x = self.block1(x)\n        x = self.block2(x)\n        x = self.block3(x)\n        x = self.flatten(x)\n        x = self.fc(x)\n        return x\n    \n    ####附加题\n    #### 11.请参考上述代码，设计一个基于1D Conv/Transformer/Mamba/等其他深度学习模型的脑电信号分类模型，并亲自跑出结果\n","metadata":{"id":"SmFhrHzSC8BE","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:30.162380Z","iopub.execute_input":"2025-05-06T05:34:30.162572Z","iopub.status.idle":"2025-05-06T05:34:30.178610Z","shell.execute_reply.started":"2025-05-06T05:34:30.162557Z","shell.execute_reply":"2025-05-06T05:34:30.178031Z"}},"outputs":[],"execution_count":15},{"cell_type":"markdown","source":"##Model Summery","metadata":{"id":"M49ks2b8C_dP"}},{"cell_type":"code","source":"input_size = (1, 22, 1001)\neegnet_model = EEGNetModel().to(device)\nsummary(eegnet_model, input_size)","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"7NdOeIRtDAOn","outputId":"35ec6ad5-7e2c-4f99-cae0-e83ffd549797","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:30.179262Z","iopub.execute_input":"2025-05-06T05:34:30.179469Z","iopub.status.idle":"2025-05-06T05:34:30.744386Z","shell.execute_reply.started":"2025-05-06T05:34:30.179448Z","shell.execute_reply":"2025-05-06T05:34:30.743778Z"}},"outputs":[{"name":"stdout","text":"==========================================================================================\nLayer (type:depth-idx)                   Output Shape              Param #\n==========================================================================================\n├─Sequential: 1-1                        [-1, 16, 22, 1001]        --\n|    └─Conv2d: 2-1                       [-1, 16, 22, 1001]        512\n|    └─BatchNorm2d: 2-2                  [-1, 16, 22, 1001]        32\n├─Sequential: 1-2                        [-1, 32, 1, 125]          --\n|    └─Conv2d: 2-3                       [-1, 32, 1, 1001]         704\n|    └─BatchNorm2d: 2-4                  [-1, 32, 1, 1001]         64\n|    └─ELU: 2-5                          [-1, 32, 1, 1001]         --\n|    └─AvgPool2d: 2-6                    [-1, 32, 1, 125]          --\n|    └─Dropout: 2-7                      [-1, 32, 1, 125]          --\n├─Sequential: 1-3                        [-1, 32, 1, 7]            --\n|    └─Conv2d: 2-8                       [-1, 32, 1, 125]          512\n|    └─Conv2d: 2-9                       [-1, 32, 1, 125]          1,024\n|    └─BatchNorm2d: 2-10                 [-1, 32, 1, 125]          64\n|    └─ELU: 2-11                         [-1, 32, 1, 125]          --\n|    └─AvgPool2d: 2-12                   [-1, 32, 1, 7]            --\n|    └─Dropout: 2-13                     [-1, 32, 1, 7]            --\n├─Flatten: 1-4                           [-1, 224]                 --\n├─Linear: 1-5                            [-1, 4]                   900\n==========================================================================================\nTotal params: 3,812\nTrainable params: 3,812\nNon-trainable params: 0\nTotal mult-adds (M): 12.18\n==========================================================================================\nInput size (MB): 0.08\nForward/backward pass size (MB): 5.96\nParams size (MB): 0.01\nEstimated Total Size (MB): 6.06\n==========================================================================================\n","output_type":"stream"},{"name":"stderr","text":"/usr/local/lib/python3.11/dist-packages/torch/nn/modules/conv.py:549: UserWarning: Using padding='same' with even kernel lengths and odd dilation may require a zero-padded copy of the input be created (Triggered internally at ../aten/src/ATen/native/Convolution.cpp:1036.)\n  return F.conv2d(\n","output_type":"stream"},{"execution_count":16,"output_type":"execute_result","data":{"text/plain":"==========================================================================================\nLayer (type:depth-idx)                   Output Shape              Param #\n==========================================================================================\n├─Sequential: 1-1                        [-1, 16, 22, 1001]        --\n|    └─Conv2d: 2-1                       [-1, 16, 22, 1001]        512\n|    └─BatchNorm2d: 2-2                  [-1, 16, 22, 1001]        32\n├─Sequential: 1-2                        [-1, 32, 1, 125]          --\n|    └─Conv2d: 2-3                       [-1, 32, 1, 1001]         704\n|    └─BatchNorm2d: 2-4                  [-1, 32, 1, 1001]         64\n|    └─ELU: 2-5                          [-1, 32, 1, 1001]         --\n|    └─AvgPool2d: 2-6                    [-1, 32, 1, 125]          --\n|    └─Dropout: 2-7                      [-1, 32, 1, 125]          --\n├─Sequential: 1-3                        [-1, 32, 1, 7]            --\n|    └─Conv2d: 2-8                       [-1, 32, 1, 125]          512\n|    └─Conv2d: 2-9                       [-1, 32, 1, 125]          1,024\n|    └─BatchNorm2d: 2-10                 [-1, 32, 1, 125]          64\n|    └─ELU: 2-11                         [-1, 32, 1, 125]          --\n|    └─AvgPool2d: 2-12                   [-1, 32, 1, 7]            --\n|    └─Dropout: 2-13                     [-1, 32, 1, 7]            --\n├─Flatten: 1-4                           [-1, 224]                 --\n├─Linear: 1-5                            [-1, 4]                   900\n==========================================================================================\nTotal params: 3,812\nTrainable params: 3,812\nNon-trainable params: 0\nTotal mult-adds (M): 12.18\n==========================================================================================\nInput size (MB): 0.08\nForward/backward pass size (MB): 5.96\nParams size (MB): 0.01\nEstimated Total Size (MB): 6.06\n=========================================================================================="},"metadata":{}}],"execution_count":16},{"cell_type":"markdown","source":"##Training Model","metadata":{"id":"95r4EymoDCIv"}},{"cell_type":"code","source":"eegnet_model = EEGNetModel().to(device)\n\n# Training Hyperparameters\nEPOCHS = 500\nBATCH_SIZE = 64\nLEARNING_RATE = 0.001\ntrainer = TrainModel()\ntrained_eegnet_model = trainer.train_model(eegnet_model, train_dataset, learning_rate=LEARNING_RATE,\n                                   batch_size=BATCH_SIZE, epochs=EPOCHS)\ntorch.save(trained_eegnet_model.state_dict(), 'eegnet_model.pth')\n","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"TJzl6On9DFcp","outputId":"7c7e7ca1-e094-478a-f7df-171e12388792","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:34:30.745105Z","iopub.execute_input":"2025-05-06T05:34:30.745349Z","iopub.status.idle":"2025-05-06T05:40:40.643501Z","shell.execute_reply.started":"2025-05-06T05:34:30.745334Z","shell.execute_reply":"2025-05-06T05:40:40.642826Z"}},"outputs":[{"name":"stdout","text":"Epoch 1/500, Loss: 1.3827, Accuracy: 28.26%\nEpoch 2/500, Loss: 1.3659, Accuracy: 30.15%\nEpoch 3/500, Loss: 1.3486, Accuracy: 33.06%\nEpoch 4/500, Loss: 1.3257, Accuracy: 36.19%\nEpoch 5/500, Loss: 1.2908, Accuracy: 38.64%\nEpoch 6/500, Loss: 1.2696, Accuracy: 40.18%\nEpoch 7/500, Loss: 1.2525, Accuracy: 42.50%\nEpoch 8/500, Loss: 1.2287, Accuracy: 43.78%\nEpoch 9/500, Loss: 1.2174, Accuracy: 42.45%\nEpoch 10/500, Loss: 1.1974, Accuracy: 44.68%\nEpoch 11/500, Loss: 1.2046, Accuracy: 45.45%\nEpoch 12/500, Loss: 1.1951, Accuracy: 44.81%\nEpoch 13/500, Loss: 1.1823, Accuracy: 45.54%\nEpoch 14/500, Loss: 1.1790, Accuracy: 44.81%\nEpoch 15/500, Loss: 1.1698, Accuracy: 46.91%\nEpoch 16/500, Loss: 1.1731, Accuracy: 45.88%\nEpoch 17/500, Loss: 1.1640, Accuracy: 47.98%\nEpoch 18/500, Loss: 1.1560, Accuracy: 47.98%\nEpoch 19/500, Loss: 1.1415, Accuracy: 47.47%\nEpoch 20/500, Loss: 1.1429, Accuracy: 47.43%\nEpoch 21/500, Loss: 1.1476, Accuracy: 47.51%\nEpoch 22/500, Loss: 1.1325, Accuracy: 49.19%\nEpoch 23/500, Loss: 1.1250, Accuracy: 49.66%\nEpoch 24/500, Loss: 1.1300, Accuracy: 48.28%\nEpoch 25/500, Loss: 1.1175, Accuracy: 50.34%\nEpoch 26/500, Loss: 1.1136, Accuracy: 49.53%\nEpoch 27/500, Loss: 1.1022, Accuracy: 51.89%\nEpoch 28/500, Loss: 1.1222, Accuracy: 49.44%\nEpoch 29/500, Loss: 1.1097, Accuracy: 50.21%\nEpoch 30/500, Loss: 1.1061, Accuracy: 50.04%\nEpoch 31/500, Loss: 1.0894, Accuracy: 52.49%\nEpoch 32/500, Loss: 1.0783, Accuracy: 53.34%\nEpoch 33/500, Loss: 1.0816, Accuracy: 51.33%\nEpoch 34/500, Loss: 1.0959, Accuracy: 51.63%\nEpoch 35/500, Loss: 1.0823, Accuracy: 52.14%\nEpoch 36/500, Loss: 1.0759, Accuracy: 53.52%\nEpoch 37/500, Loss: 1.0879, Accuracy: 51.20%\nEpoch 38/500, Loss: 1.0765, Accuracy: 52.53%\nEpoch 39/500, Loss: 1.0870, Accuracy: 51.46%\nEpoch 40/500, Loss: 1.0625, Accuracy: 53.17%\nEpoch 41/500, Loss: 1.0769, Accuracy: 52.70%\nEpoch 42/500, Loss: 1.0559, Accuracy: 54.97%\nEpoch 43/500, Loss: 1.0602, Accuracy: 53.69%\nEpoch 44/500, Loss: 1.0633, Accuracy: 53.77%\nEpoch 45/500, Loss: 1.0593, Accuracy: 52.44%\nEpoch 46/500, Loss: 1.0757, Accuracy: 52.87%\nEpoch 47/500, Loss: 1.0534, Accuracy: 54.29%\nEpoch 48/500, Loss: 1.0476, Accuracy: 55.49%\nEpoch 49/500, Loss: 1.0590, Accuracy: 53.77%\nEpoch 50/500, Loss: 1.0400, Accuracy: 54.03%\nEpoch 51/500, Loss: 1.0450, Accuracy: 54.63%\nEpoch 52/500, Loss: 1.0541, Accuracy: 53.73%\nEpoch 53/500, Loss: 1.0332, Accuracy: 55.10%\nEpoch 54/500, Loss: 1.0328, Accuracy: 55.02%\nEpoch 55/500, Loss: 1.0443, Accuracy: 55.02%\nEpoch 56/500, Loss: 1.0268, Accuracy: 56.56%\nEpoch 57/500, Loss: 1.0137, Accuracy: 55.92%\nEpoch 58/500, Loss: 1.0302, Accuracy: 54.93%\nEpoch 59/500, Loss: 1.0290, Accuracy: 54.46%\nEpoch 60/500, Loss: 1.0125, Accuracy: 56.43%\nEpoch 61/500, Loss: 1.0242, Accuracy: 55.06%\nEpoch 62/500, Loss: 1.0207, Accuracy: 54.89%\nEpoch 63/500, Loss: 1.0370, Accuracy: 54.67%\nEpoch 64/500, Loss: 1.0249, Accuracy: 55.62%\nEpoch 65/500, Loss: 1.0300, Accuracy: 54.97%\nEpoch 66/500, Loss: 1.0082, Accuracy: 56.17%\nEpoch 67/500, Loss: 1.0195, Accuracy: 55.36%\nEpoch 68/500, Loss: 1.0203, Accuracy: 56.05%\nEpoch 69/500, Loss: 1.0190, Accuracy: 56.82%\nEpoch 70/500, Loss: 1.0124, Accuracy: 55.92%\nEpoch 71/500, Loss: 0.9890, Accuracy: 57.42%\nEpoch 72/500, Loss: 1.0032, Accuracy: 57.63%\nEpoch 73/500, Loss: 1.0091, Accuracy: 55.70%\nEpoch 74/500, Loss: 0.9915, Accuracy: 56.60%\nEpoch 75/500, Loss: 1.0169, Accuracy: 55.79%\nEpoch 76/500, Loss: 0.9856, Accuracy: 57.12%\nEpoch 77/500, Loss: 1.0033, Accuracy: 56.48%\nEpoch 78/500, Loss: 1.0014, Accuracy: 57.25%\nEpoch 79/500, Loss: 0.9925, Accuracy: 58.15%\nEpoch 80/500, Loss: 0.9900, Accuracy: 57.55%\nEpoch 81/500, Loss: 0.9931, Accuracy: 57.16%\nEpoch 82/500, Loss: 0.9932, Accuracy: 57.76%\nEpoch 83/500, Loss: 0.9829, Accuracy: 58.06%\nEpoch 84/500, Loss: 0.9954, Accuracy: 57.08%\nEpoch 85/500, Loss: 0.9916, Accuracy: 57.68%\nEpoch 86/500, Loss: 0.9871, Accuracy: 58.88%\nEpoch 87/500, Loss: 0.9878, Accuracy: 57.98%\nEpoch 88/500, Loss: 0.9700, Accuracy: 57.68%\nEpoch 89/500, Loss: 0.9880, Accuracy: 57.68%\nEpoch 90/500, Loss: 0.9780, Accuracy: 57.93%\nEpoch 91/500, Loss: 0.9640, Accuracy: 59.69%\nEpoch 92/500, Loss: 0.9568, Accuracy: 60.16%\nEpoch 93/500, Loss: 0.9791, Accuracy: 58.23%\nEpoch 94/500, Loss: 0.9640, Accuracy: 58.88%\nEpoch 95/500, Loss: 0.9702, Accuracy: 59.01%\nEpoch 96/500, Loss: 0.9599, Accuracy: 58.62%\nEpoch 97/500, Loss: 0.9667, Accuracy: 59.73%\nEpoch 98/500, Loss: 0.9732, Accuracy: 59.82%\nEpoch 99/500, Loss: 0.9508, Accuracy: 59.52%\nEpoch 100/500, Loss: 0.9492, Accuracy: 59.86%\nEpoch 101/500, Loss: 0.9603, Accuracy: 58.96%\nEpoch 102/500, Loss: 0.9398, Accuracy: 60.25%\nEpoch 103/500, Loss: 0.9443, Accuracy: 59.86%\nEpoch 104/500, Loss: 0.9768, Accuracy: 59.73%\nEpoch 105/500, Loss: 0.9664, Accuracy: 59.35%\nEpoch 106/500, Loss: 0.9327, Accuracy: 60.42%\nEpoch 107/500, Loss: 0.9506, Accuracy: 59.61%\nEpoch 108/500, Loss: 0.9569, Accuracy: 59.39%\nEpoch 109/500, Loss: 0.9421, Accuracy: 60.29%\nEpoch 110/500, Loss: 0.9303, Accuracy: 60.03%\nEpoch 111/500, Loss: 0.9424, Accuracy: 59.31%\nEpoch 112/500, Loss: 0.9270, Accuracy: 61.88%\nEpoch 113/500, Loss: 0.9350, Accuracy: 59.91%\nEpoch 114/500, Loss: 0.9362, Accuracy: 60.12%\nEpoch 115/500, Loss: 0.9371, Accuracy: 61.19%\nEpoch 116/500, Loss: 0.9294, Accuracy: 62.14%\nEpoch 117/500, Loss: 0.9330, Accuracy: 60.38%\nEpoch 118/500, Loss: 0.9373, Accuracy: 60.59%\nEpoch 119/500, Loss: 0.9290, Accuracy: 61.06%\nEpoch 120/500, Loss: 0.9337, Accuracy: 59.35%\nEpoch 121/500, Loss: 0.9443, Accuracy: 60.33%\nEpoch 122/500, Loss: 0.9231, Accuracy: 61.28%\nEpoch 123/500, Loss: 0.9137, Accuracy: 62.31%\nEpoch 124/500, Loss: 0.9206, Accuracy: 61.84%\nEpoch 125/500, Loss: 0.9266, Accuracy: 60.98%\nEpoch 126/500, Loss: 0.9201, Accuracy: 60.81%\nEpoch 127/500, Loss: 0.9252, Accuracy: 60.93%\nEpoch 128/500, Loss: 0.9205, Accuracy: 61.79%\nEpoch 129/500, Loss: 0.9183, Accuracy: 61.11%\nEpoch 130/500, Loss: 0.9162, Accuracy: 60.46%\nEpoch 131/500, Loss: 0.9181, Accuracy: 62.35%\nEpoch 132/500, Loss: 0.9070, Accuracy: 62.82%\nEpoch 133/500, Loss: 0.9033, Accuracy: 62.14%\nEpoch 134/500, Loss: 0.9370, Accuracy: 60.42%\nEpoch 135/500, Loss: 0.9182, Accuracy: 61.54%\nEpoch 136/500, Loss: 0.9156, Accuracy: 61.32%\nEpoch 137/500, Loss: 0.9153, Accuracy: 61.49%\nEpoch 138/500, Loss: 0.9037, Accuracy: 62.78%\nEpoch 139/500, Loss: 0.9049, Accuracy: 60.93%\nEpoch 140/500, Loss: 0.9147, Accuracy: 61.36%\nEpoch 141/500, Loss: 0.9127, Accuracy: 62.44%\nEpoch 142/500, Loss: 0.9193, Accuracy: 61.71%\nEpoch 143/500, Loss: 0.9016, Accuracy: 62.78%\nEpoch 144/500, Loss: 0.9034, Accuracy: 63.34%\nEpoch 145/500, Loss: 0.8978, Accuracy: 62.95%\nEpoch 146/500, Loss: 0.9096, Accuracy: 61.41%\nEpoch 147/500, Loss: 0.8772, Accuracy: 62.86%\nEpoch 148/500, Loss: 0.8927, Accuracy: 63.34%\nEpoch 149/500, Loss: 0.8910, Accuracy: 62.99%\nEpoch 150/500, Loss: 0.8788, Accuracy: 62.99%\nEpoch 151/500, Loss: 0.8999, Accuracy: 63.89%\nEpoch 152/500, Loss: 0.9168, Accuracy: 63.12%\nEpoch 153/500, Loss: 0.8848, Accuracy: 63.42%\nEpoch 154/500, Loss: 0.9044, Accuracy: 62.52%\nEpoch 155/500, Loss: 0.9073, Accuracy: 62.01%\nEpoch 156/500, Loss: 0.8865, Accuracy: 63.12%\nEpoch 157/500, Loss: 0.8859, Accuracy: 62.48%\nEpoch 158/500, Loss: 0.8700, Accuracy: 61.96%\nEpoch 159/500, Loss: 0.9006, Accuracy: 61.96%\nEpoch 160/500, Loss: 0.8921, Accuracy: 63.25%\nEpoch 161/500, Loss: 0.8969, Accuracy: 63.81%\nEpoch 162/500, Loss: 0.8981, Accuracy: 63.72%\nEpoch 163/500, Loss: 0.8927, Accuracy: 62.91%\nEpoch 164/500, Loss: 0.8844, Accuracy: 63.12%\nEpoch 165/500, Loss: 0.8615, Accuracy: 65.01%\nEpoch 166/500, Loss: 0.8744, Accuracy: 64.07%\nEpoch 167/500, Loss: 0.8826, Accuracy: 64.37%\nEpoch 168/500, Loss: 0.8774, Accuracy: 64.54%\nEpoch 169/500, Loss: 0.8919, Accuracy: 62.35%\nEpoch 170/500, Loss: 0.8777, Accuracy: 63.42%\nEpoch 171/500, Loss: 0.8798, Accuracy: 62.95%\nEpoch 172/500, Loss: 0.8852, Accuracy: 62.22%\nEpoch 173/500, Loss: 0.8621, Accuracy: 63.64%\nEpoch 174/500, Loss: 0.8965, Accuracy: 62.91%\nEpoch 175/500, Loss: 0.8723, Accuracy: 65.09%\nEpoch 176/500, Loss: 0.8741, Accuracy: 63.64%\nEpoch 177/500, Loss: 0.9021, Accuracy: 63.21%\nEpoch 178/500, Loss: 0.8814, Accuracy: 63.16%\nEpoch 179/500, Loss: 0.8810, Accuracy: 63.38%\nEpoch 180/500, Loss: 0.8651, Accuracy: 64.71%\nEpoch 181/500, Loss: 0.8910, Accuracy: 63.42%\nEpoch 182/500, Loss: 0.8952, Accuracy: 62.78%\nEpoch 183/500, Loss: 0.8646, Accuracy: 64.71%\nEpoch 184/500, Loss: 0.8701, Accuracy: 65.09%\nEpoch 185/500, Loss: 0.8526, Accuracy: 64.62%\nEpoch 186/500, Loss: 0.8681, Accuracy: 63.64%\nEpoch 187/500, Loss: 0.8728, Accuracy: 63.46%\nEpoch 188/500, Loss: 0.8420, Accuracy: 64.75%\nEpoch 189/500, Loss: 0.8586, Accuracy: 64.11%\nEpoch 190/500, Loss: 0.8598, Accuracy: 64.24%\nEpoch 191/500, Loss: 0.8731, Accuracy: 63.55%\nEpoch 192/500, Loss: 0.8641, Accuracy: 64.58%\nEpoch 193/500, Loss: 0.8678, Accuracy: 63.55%\nEpoch 194/500, Loss: 0.8752, Accuracy: 62.95%\nEpoch 195/500, Loss: 0.8991, Accuracy: 63.25%\nEpoch 196/500, Loss: 0.8548, Accuracy: 65.01%\nEpoch 197/500, Loss: 0.8550, Accuracy: 64.88%\nEpoch 198/500, Loss: 0.8525, Accuracy: 64.84%\nEpoch 199/500, Loss: 0.8561, Accuracy: 64.92%\nEpoch 200/500, Loss: 0.8621, Accuracy: 65.31%\nEpoch 201/500, Loss: 0.8628, Accuracy: 64.54%\nEpoch 202/500, Loss: 0.8754, Accuracy: 63.68%\nEpoch 203/500, Loss: 0.8446, Accuracy: 65.99%\nEpoch 204/500, Loss: 0.8618, Accuracy: 63.72%\nEpoch 205/500, Loss: 0.8552, Accuracy: 64.02%\nEpoch 206/500, Loss: 0.8447, Accuracy: 66.04%\nEpoch 207/500, Loss: 0.8542, Accuracy: 64.49%\nEpoch 208/500, Loss: 0.8578, Accuracy: 64.88%\nEpoch 209/500, Loss: 0.8589, Accuracy: 64.79%\nEpoch 210/500, Loss: 0.8410, Accuracy: 65.44%\nEpoch 211/500, Loss: 0.8441, Accuracy: 65.44%\nEpoch 212/500, Loss: 0.8667, Accuracy: 64.41%\nEpoch 213/500, Loss: 0.8397, Accuracy: 64.75%\nEpoch 214/500, Loss: 0.8411, Accuracy: 64.07%\nEpoch 215/500, Loss: 0.8560, Accuracy: 64.15%\nEpoch 216/500, Loss: 0.8608, Accuracy: 64.24%\nEpoch 217/500, Loss: 0.8491, Accuracy: 65.39%\nEpoch 218/500, Loss: 0.8526, Accuracy: 63.55%\nEpoch 219/500, Loss: 0.8515, Accuracy: 64.79%\nEpoch 220/500, Loss: 0.8643, Accuracy: 63.55%\nEpoch 221/500, Loss: 0.8651, Accuracy: 64.84%\nEpoch 222/500, Loss: 0.8505, Accuracy: 65.91%\nEpoch 223/500, Loss: 0.8555, Accuracy: 65.35%\nEpoch 224/500, Loss: 0.8306, Accuracy: 66.12%\nEpoch 225/500, Loss: 0.8374, Accuracy: 65.95%\nEpoch 226/500, Loss: 0.8271, Accuracy: 66.90%\nEpoch 227/500, Loss: 0.8423, Accuracy: 65.09%\nEpoch 228/500, Loss: 0.8494, Accuracy: 65.18%\nEpoch 229/500, Loss: 0.8641, Accuracy: 63.89%\nEpoch 230/500, Loss: 0.8370, Accuracy: 65.52%\nEpoch 231/500, Loss: 0.8444, Accuracy: 65.65%\nEpoch 232/500, Loss: 0.8493, Accuracy: 65.57%\nEpoch 233/500, Loss: 0.8348, Accuracy: 65.09%\nEpoch 234/500, Loss: 0.8349, Accuracy: 65.74%\nEpoch 235/500, Loss: 0.8397, Accuracy: 65.35%\nEpoch 236/500, Loss: 0.8449, Accuracy: 65.39%\nEpoch 237/500, Loss: 0.8295, Accuracy: 66.85%\nEpoch 238/500, Loss: 0.8223, Accuracy: 67.20%\nEpoch 239/500, Loss: 0.8302, Accuracy: 66.72%\nEpoch 240/500, Loss: 0.8305, Accuracy: 65.61%\nEpoch 241/500, Loss: 0.8150, Accuracy: 66.47%\nEpoch 242/500, Loss: 0.8257, Accuracy: 66.77%\nEpoch 243/500, Loss: 0.8286, Accuracy: 66.64%\nEpoch 244/500, Loss: 0.8403, Accuracy: 66.42%\nEpoch 245/500, Loss: 0.8444, Accuracy: 65.91%\nEpoch 246/500, Loss: 0.8408, Accuracy: 64.32%\nEpoch 247/500, Loss: 0.8340, Accuracy: 65.39%\nEpoch 248/500, Loss: 0.8406, Accuracy: 64.97%\nEpoch 249/500, Loss: 0.8164, Accuracy: 67.32%\nEpoch 250/500, Loss: 0.8153, Accuracy: 66.47%\nEpoch 251/500, Loss: 0.8275, Accuracy: 67.54%\nEpoch 252/500, Loss: 0.8152, Accuracy: 67.11%\nEpoch 253/500, Loss: 0.8368, Accuracy: 66.12%\nEpoch 254/500, Loss: 0.8357, Accuracy: 66.47%\nEpoch 255/500, Loss: 0.8430, Accuracy: 64.58%\nEpoch 256/500, Loss: 0.8395, Accuracy: 66.64%\nEpoch 257/500, Loss: 0.7930, Accuracy: 67.92%\nEpoch 258/500, Loss: 0.8388, Accuracy: 65.18%\nEpoch 259/500, Loss: 0.8338, Accuracy: 64.79%\nEpoch 260/500, Loss: 0.8268, Accuracy: 66.38%\nEpoch 261/500, Loss: 0.8105, Accuracy: 67.92%\nEpoch 262/500, Loss: 0.8274, Accuracy: 65.74%\nEpoch 263/500, Loss: 0.8269, Accuracy: 67.24%\nEpoch 264/500, Loss: 0.8275, Accuracy: 66.30%\nEpoch 265/500, Loss: 0.8118, Accuracy: 67.20%\nEpoch 266/500, Loss: 0.8097, Accuracy: 66.94%\nEpoch 267/500, Loss: 0.8171, Accuracy: 68.10%\nEpoch 268/500, Loss: 0.8367, Accuracy: 65.99%\nEpoch 269/500, Loss: 0.8293, Accuracy: 66.98%\nEpoch 270/500, Loss: 0.8263, Accuracy: 65.91%\nEpoch 271/500, Loss: 0.8231, Accuracy: 65.78%\nEpoch 272/500, Loss: 0.8373, Accuracy: 64.54%\nEpoch 273/500, Loss: 0.8388, Accuracy: 65.01%\nEpoch 274/500, Loss: 0.8126, Accuracy: 67.24%\nEpoch 275/500, Loss: 0.8450, Accuracy: 65.65%\nEpoch 276/500, Loss: 0.8113, Accuracy: 67.80%\nEpoch 277/500, Loss: 0.8171, Accuracy: 67.58%\nEpoch 278/500, Loss: 0.8122, Accuracy: 68.05%\nEpoch 279/500, Loss: 0.8169, Accuracy: 67.37%\nEpoch 280/500, Loss: 0.8069, Accuracy: 67.54%\nEpoch 281/500, Loss: 0.8282, Accuracy: 67.41%\nEpoch 282/500, Loss: 0.8076, Accuracy: 66.47%\nEpoch 283/500, Loss: 0.8115, Accuracy: 66.72%\nEpoch 284/500, Loss: 0.8168, Accuracy: 67.62%\nEpoch 285/500, Loss: 0.8271, Accuracy: 66.25%\nEpoch 286/500, Loss: 0.8109, Accuracy: 67.80%\nEpoch 287/500, Loss: 0.8160, Accuracy: 67.20%\nEpoch 288/500, Loss: 0.8144, Accuracy: 66.38%\nEpoch 289/500, Loss: 0.8124, Accuracy: 67.45%\nEpoch 290/500, Loss: 0.8267, Accuracy: 65.48%\nEpoch 291/500, Loss: 0.8072, Accuracy: 67.15%\nEpoch 292/500, Loss: 0.8066, Accuracy: 66.81%\nEpoch 293/500, Loss: 0.7937, Accuracy: 68.35%\nEpoch 294/500, Loss: 0.8163, Accuracy: 66.08%\nEpoch 295/500, Loss: 0.8259, Accuracy: 66.47%\nEpoch 296/500, Loss: 0.8231, Accuracy: 66.04%\nEpoch 297/500, Loss: 0.8160, Accuracy: 66.38%\nEpoch 298/500, Loss: 0.8206, Accuracy: 66.34%\nEpoch 299/500, Loss: 0.8001, Accuracy: 67.58%\nEpoch 300/500, Loss: 0.8077, Accuracy: 67.97%\nEpoch 301/500, Loss: 0.7868, Accuracy: 68.35%\nEpoch 302/500, Loss: 0.8305, Accuracy: 65.99%\nEpoch 303/500, Loss: 0.8013, Accuracy: 66.98%\nEpoch 304/500, Loss: 0.8289, Accuracy: 66.38%\nEpoch 305/500, Loss: 0.8095, Accuracy: 67.80%\nEpoch 306/500, Loss: 0.8207, Accuracy: 66.72%\nEpoch 307/500, Loss: 0.8108, Accuracy: 67.67%\nEpoch 308/500, Loss: 0.7792, Accuracy: 69.55%\nEpoch 309/500, Loss: 0.7953, Accuracy: 68.91%\nEpoch 310/500, Loss: 0.8087, Accuracy: 67.24%\nEpoch 311/500, Loss: 0.8000, Accuracy: 66.64%\nEpoch 312/500, Loss: 0.8192, Accuracy: 67.28%\nEpoch 313/500, Loss: 0.8026, Accuracy: 67.88%\nEpoch 314/500, Loss: 0.7847, Accuracy: 68.40%\nEpoch 315/500, Loss: 0.8128, Accuracy: 67.50%\nEpoch 316/500, Loss: 0.8041, Accuracy: 66.94%\nEpoch 317/500, Loss: 0.7980, Accuracy: 67.45%\nEpoch 318/500, Loss: 0.8047, Accuracy: 67.54%\nEpoch 319/500, Loss: 0.7988, Accuracy: 66.90%\nEpoch 320/500, Loss: 0.7805, Accuracy: 68.44%\nEpoch 321/500, Loss: 0.7941, Accuracy: 68.70%\nEpoch 322/500, Loss: 0.7792, Accuracy: 68.74%\nEpoch 323/500, Loss: 0.7954, Accuracy: 67.37%\nEpoch 324/500, Loss: 0.7864, Accuracy: 67.58%\nEpoch 325/500, Loss: 0.7953, Accuracy: 67.62%\nEpoch 326/500, Loss: 0.7858, Accuracy: 67.75%\nEpoch 327/500, Loss: 0.7899, Accuracy: 67.71%\nEpoch 328/500, Loss: 0.7968, Accuracy: 68.83%\nEpoch 329/500, Loss: 0.7854, Accuracy: 67.71%\nEpoch 330/500, Loss: 0.7989, Accuracy: 67.54%\nEpoch 331/500, Loss: 0.7922, Accuracy: 67.15%\nEpoch 332/500, Loss: 0.8092, Accuracy: 67.37%\nEpoch 333/500, Loss: 0.8019, Accuracy: 68.83%\nEpoch 334/500, Loss: 0.7756, Accuracy: 68.78%\nEpoch 335/500, Loss: 0.7998, Accuracy: 66.94%\nEpoch 336/500, Loss: 0.8030, Accuracy: 67.15%\nEpoch 337/500, Loss: 0.7838, Accuracy: 68.65%\nEpoch 338/500, Loss: 0.8109, Accuracy: 67.54%\nEpoch 339/500, Loss: 0.8070, Accuracy: 66.81%\nEpoch 340/500, Loss: 0.7770, Accuracy: 68.27%\nEpoch 341/500, Loss: 0.7814, Accuracy: 67.24%\nEpoch 342/500, Loss: 0.8113, Accuracy: 67.28%\nEpoch 343/500, Loss: 0.7994, Accuracy: 68.05%\nEpoch 344/500, Loss: 0.7920, Accuracy: 66.90%\nEpoch 345/500, Loss: 0.7913, Accuracy: 67.62%\nEpoch 346/500, Loss: 0.7857, Accuracy: 67.11%\nEpoch 347/500, Loss: 0.7871, Accuracy: 68.74%\nEpoch 348/500, Loss: 0.8064, Accuracy: 67.37%\nEpoch 349/500, Loss: 0.7832, Accuracy: 68.40%\nEpoch 350/500, Loss: 0.7928, Accuracy: 68.01%\nEpoch 351/500, Loss: 0.7853, Accuracy: 68.10%\nEpoch 352/500, Loss: 0.7829, Accuracy: 68.91%\nEpoch 353/500, Loss: 0.7921, Accuracy: 67.54%\nEpoch 354/500, Loss: 0.7859, Accuracy: 68.74%\nEpoch 355/500, Loss: 0.7928, Accuracy: 68.48%\nEpoch 356/500, Loss: 0.7895, Accuracy: 69.00%\nEpoch 357/500, Loss: 0.7851, Accuracy: 68.18%\nEpoch 358/500, Loss: 0.7845, Accuracy: 68.74%\nEpoch 359/500, Loss: 0.7800, Accuracy: 68.87%\nEpoch 360/500, Loss: 0.7707, Accuracy: 68.57%\nEpoch 361/500, Loss: 0.8009, Accuracy: 67.11%\nEpoch 362/500, Loss: 0.7665, Accuracy: 69.73%\nEpoch 363/500, Loss: 0.8048, Accuracy: 67.62%\nEpoch 364/500, Loss: 0.7733, Accuracy: 68.91%\nEpoch 365/500, Loss: 0.7681, Accuracy: 68.70%\nEpoch 366/500, Loss: 0.7626, Accuracy: 68.61%\nEpoch 367/500, Loss: 0.7834, Accuracy: 68.14%\nEpoch 368/500, Loss: 0.7817, Accuracy: 69.04%\nEpoch 369/500, Loss: 0.7792, Accuracy: 69.04%\nEpoch 370/500, Loss: 0.8134, Accuracy: 66.34%\nEpoch 371/500, Loss: 0.7914, Accuracy: 68.44%\nEpoch 372/500, Loss: 0.7996, Accuracy: 66.94%\nEpoch 373/500, Loss: 0.7803, Accuracy: 68.91%\nEpoch 374/500, Loss: 0.7859, Accuracy: 68.10%\nEpoch 375/500, Loss: 0.7848, Accuracy: 68.83%\nEpoch 376/500, Loss: 0.7858, Accuracy: 68.31%\nEpoch 377/500, Loss: 0.7748, Accuracy: 69.81%\nEpoch 378/500, Loss: 0.7669, Accuracy: 69.25%\nEpoch 379/500, Loss: 0.7695, Accuracy: 67.54%\nEpoch 380/500, Loss: 0.7645, Accuracy: 68.74%\nEpoch 381/500, Loss: 0.7762, Accuracy: 67.97%\nEpoch 382/500, Loss: 0.7770, Accuracy: 67.20%\nEpoch 383/500, Loss: 0.8091, Accuracy: 66.98%\nEpoch 384/500, Loss: 0.7754, Accuracy: 69.30%\nEpoch 385/500, Loss: 0.7914, Accuracy: 68.14%\nEpoch 386/500, Loss: 0.7685, Accuracy: 69.38%\nEpoch 387/500, Loss: 0.7746, Accuracy: 68.14%\nEpoch 388/500, Loss: 0.7515, Accuracy: 69.77%\nEpoch 389/500, Loss: 0.7703, Accuracy: 69.21%\nEpoch 390/500, Loss: 0.7655, Accuracy: 69.51%\nEpoch 391/500, Loss: 0.7859, Accuracy: 68.01%\nEpoch 392/500, Loss: 0.7813, Accuracy: 68.52%\nEpoch 393/500, Loss: 0.7748, Accuracy: 67.84%\nEpoch 394/500, Loss: 0.7664, Accuracy: 69.77%\nEpoch 395/500, Loss: 0.7858, Accuracy: 67.15%\nEpoch 396/500, Loss: 0.7910, Accuracy: 68.65%\nEpoch 397/500, Loss: 0.8067, Accuracy: 68.48%\nEpoch 398/500, Loss: 0.7681, Accuracy: 69.21%\nEpoch 399/500, Loss: 0.7662, Accuracy: 69.77%\nEpoch 400/500, Loss: 0.7773, Accuracy: 67.84%\nEpoch 401/500, Loss: 0.7804, Accuracy: 67.41%\nEpoch 402/500, Loss: 0.7667, Accuracy: 69.73%\nEpoch 403/500, Loss: 0.7542, Accuracy: 70.84%\nEpoch 404/500, Loss: 0.7850, Accuracy: 69.13%\nEpoch 405/500, Loss: 0.7854, Accuracy: 68.27%\nEpoch 406/500, Loss: 0.7803, Accuracy: 68.78%\nEpoch 407/500, Loss: 0.7902, Accuracy: 66.94%\nEpoch 408/500, Loss: 0.7674, Accuracy: 69.77%\nEpoch 409/500, Loss: 0.7664, Accuracy: 68.83%\nEpoch 410/500, Loss: 0.7618, Accuracy: 69.64%\nEpoch 411/500, Loss: 0.7756, Accuracy: 68.48%\nEpoch 412/500, Loss: 0.7612, Accuracy: 70.03%\nEpoch 413/500, Loss: 0.7741, Accuracy: 68.57%\nEpoch 414/500, Loss: 0.7623, Accuracy: 68.83%\nEpoch 415/500, Loss: 0.7737, Accuracy: 68.27%\nEpoch 416/500, Loss: 0.7746, Accuracy: 68.57%\nEpoch 417/500, Loss: 0.7761, Accuracy: 68.35%\nEpoch 418/500, Loss: 0.7453, Accuracy: 70.33%\nEpoch 419/500, Loss: 0.7839, Accuracy: 67.84%\nEpoch 420/500, Loss: 0.7504, Accuracy: 70.28%\nEpoch 421/500, Loss: 0.7640, Accuracy: 68.95%\nEpoch 422/500, Loss: 0.7727, Accuracy: 68.27%\nEpoch 423/500, Loss: 0.7754, Accuracy: 69.21%\nEpoch 424/500, Loss: 0.7774, Accuracy: 68.91%\nEpoch 425/500, Loss: 0.7514, Accuracy: 70.07%\nEpoch 426/500, Loss: 0.7653, Accuracy: 69.21%\nEpoch 427/500, Loss: 0.7607, Accuracy: 69.00%\nEpoch 428/500, Loss: 0.7914, Accuracy: 68.22%\nEpoch 429/500, Loss: 0.7818, Accuracy: 68.35%\nEpoch 430/500, Loss: 0.7815, Accuracy: 69.51%\nEpoch 431/500, Loss: 0.7800, Accuracy: 68.91%\nEpoch 432/500, Loss: 0.7800, Accuracy: 68.22%\nEpoch 433/500, Loss: 0.7648, Accuracy: 70.24%\nEpoch 434/500, Loss: 0.7760, Accuracy: 68.83%\nEpoch 435/500, Loss: 0.7823, Accuracy: 69.17%\nEpoch 436/500, Loss: 0.7677, Accuracy: 68.83%\nEpoch 437/500, Loss: 0.7693, Accuracy: 68.83%\nEpoch 438/500, Loss: 0.7606, Accuracy: 69.64%\nEpoch 439/500, Loss: 0.7654, Accuracy: 68.78%\nEpoch 440/500, Loss: 0.7636, Accuracy: 70.11%\nEpoch 441/500, Loss: 0.8040, Accuracy: 68.70%\nEpoch 442/500, Loss: 0.7617, Accuracy: 69.25%\nEpoch 443/500, Loss: 0.7403, Accuracy: 69.43%\nEpoch 444/500, Loss: 0.7813, Accuracy: 68.61%\nEpoch 445/500, Loss: 0.7622, Accuracy: 69.34%\nEpoch 446/500, Loss: 0.7729, Accuracy: 68.83%\nEpoch 447/500, Loss: 0.7491, Accuracy: 69.94%\nEpoch 448/500, Loss: 0.7446, Accuracy: 69.64%\nEpoch 449/500, Loss: 0.7686, Accuracy: 68.74%\nEpoch 450/500, Loss: 0.7708, Accuracy: 69.04%\nEpoch 451/500, Loss: 0.7684, Accuracy: 69.04%\nEpoch 452/500, Loss: 0.7641, Accuracy: 68.95%\nEpoch 453/500, Loss: 0.7747, Accuracy: 68.10%\nEpoch 454/500, Loss: 0.7573, Accuracy: 70.75%\nEpoch 455/500, Loss: 0.7350, Accuracy: 70.84%\nEpoch 456/500, Loss: 0.7693, Accuracy: 68.95%\nEpoch 457/500, Loss: 0.7616, Accuracy: 70.41%\nEpoch 458/500, Loss: 0.7409, Accuracy: 70.41%\nEpoch 459/500, Loss: 0.7471, Accuracy: 71.01%\nEpoch 460/500, Loss: 0.7611, Accuracy: 68.74%\nEpoch 461/500, Loss: 0.7668, Accuracy: 69.81%\nEpoch 462/500, Loss: 0.7713, Accuracy: 69.00%\nEpoch 463/500, Loss: 0.7536, Accuracy: 69.98%\nEpoch 464/500, Loss: 0.7613, Accuracy: 69.64%\nEpoch 465/500, Loss: 0.7342, Accuracy: 69.38%\nEpoch 466/500, Loss: 0.7480, Accuracy: 70.03%\nEpoch 467/500, Loss: 0.7654, Accuracy: 69.08%\nEpoch 468/500, Loss: 0.7349, Accuracy: 71.23%\nEpoch 469/500, Loss: 0.7303, Accuracy: 71.23%\nEpoch 470/500, Loss: 0.7389, Accuracy: 69.98%\nEpoch 471/500, Loss: 0.7662, Accuracy: 69.38%\nEpoch 472/500, Loss: 0.7692, Accuracy: 69.34%\nEpoch 473/500, Loss: 0.7624, Accuracy: 70.24%\nEpoch 474/500, Loss: 0.7617, Accuracy: 68.83%\nEpoch 475/500, Loss: 0.7667, Accuracy: 68.48%\nEpoch 476/500, Loss: 0.7627, Accuracy: 68.22%\nEpoch 477/500, Loss: 0.7465, Accuracy: 70.15%\nEpoch 478/500, Loss: 0.7620, Accuracy: 70.28%\nEpoch 479/500, Loss: 0.7663, Accuracy: 69.13%\nEpoch 480/500, Loss: 0.7508, Accuracy: 70.07%\nEpoch 481/500, Loss: 0.7456, Accuracy: 70.67%\nEpoch 482/500, Loss: 0.7522, Accuracy: 70.07%\nEpoch 483/500, Loss: 0.7585, Accuracy: 69.13%\nEpoch 484/500, Loss: 0.7638, Accuracy: 68.78%\nEpoch 485/500, Loss: 0.7471, Accuracy: 68.78%\nEpoch 486/500, Loss: 0.7301, Accuracy: 69.73%\nEpoch 487/500, Loss: 0.7783, Accuracy: 69.30%\nEpoch 488/500, Loss: 0.7595, Accuracy: 69.21%\nEpoch 489/500, Loss: 0.7568, Accuracy: 70.15%\nEpoch 490/500, Loss: 0.7717, Accuracy: 69.08%\nEpoch 491/500, Loss: 0.7547, Accuracy: 70.15%\nEpoch 492/500, Loss: 0.7536, Accuracy: 70.07%\nEpoch 493/500, Loss: 0.7574, Accuracy: 68.91%\nEpoch 494/500, Loss: 0.7607, Accuracy: 69.77%\nEpoch 495/500, Loss: 0.7539, Accuracy: 69.64%\nEpoch 496/500, Loss: 0.7404, Accuracy: 70.03%\nEpoch 497/500, Loss: 0.7394, Accuracy: 70.41%\nEpoch 498/500, Loss: 0.7477, Accuracy: 70.54%\nEpoch 499/500, Loss: 0.7672, Accuracy: 67.88%\nEpoch 500/500, Loss: 0.7713, Accuracy: 69.81%\nAverage Loss: 0.7712787411225189\nHighest Train Accuracy: 0.7122641509433962\n","output_type":"stream"}],"execution_count":17},{"cell_type":"markdown","source":"##Evaluating Model","metadata":{"id":"-3fKnNHxDKwn"}},{"cell_type":"code","source":"classes_list = ['Left', 'Right', 'Foot', 'Tongue']\neval_model = EvalModel(trained_eegnet_model)\ntest_accuracy = eval_model.test_model(test_dataset)\neval_model.plot_confusion_matrix(test_dataset, classes_list)\n","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":695},"id":"aHsstvZSDLb1","outputId":"62367285-83e7-4ed4-db94-376f791fcfec","trusted":true,"execution":{"iopub.status.busy":"2025-05-06T05:40:40.644278Z","iopub.execute_input":"2025-05-06T05:40:40.644703Z","iopub.status.idle":"2025-05-06T05:40:41.441242Z","shell.execute_reply.started":"2025-05-06T05:40:40.644684Z","shell.execute_reply":"2025-05-06T05:40:41.440496Z"}},"outputs":[{"name":"stdout","text":"/------------------------------/\nTest Accuracy: 67.69%\n/------------------------------/\n","output_type":"stream"},{"output_type":"display_data","data":{"text/plain":"<Figure size 1000x700 with 2 Axes>","image/png":"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69bq4IEIfdD3feXLn1+PPtbYGZcIpJlLfD38448/avXq1XrooYdM7SVKlNDx4yyik1aLftwmf7+cGtjpKQXkzaVdEaf1TOeJ9onQRQrkMVUUPv5y1e1nkr/ztArl91HUxata8cseDf5sub1Pvjw5NW1YGxXwz61LV29qz8HTav7O51r35/4Mvz64jkebPK5LsTGaOWWiYqKjFFyytD4ZN9k+7OP8ubOmakH5iiH6YNjHmj75M305abwKFwnUsBHjVTS4hL3PwA9HaurEcRo+qI8uX76kgAIF1f7tLmrR6sUMvz64joaNH1fsxYua9eXnuhgdpeASpfTR2En2idDnz0XKYv37O7ByFUPUd8jHmjllgmZM/lSFizyswZ+Y77WY6Av64tORt4cq+edTk8eb69U33srwa4NrefyJJ3UxJkaff/apoqIuqFTpMvr8iy+V939DkiLPnpU1yZNtQipXUfiIUfrs03GaMG6MHg4M0rgJE1WiREl7n3btO+rGjRsaOnigrly5rMpVqurzL76Up6dnsvPDNWSWb/4zisUwnD+7K1euXNq2bZtKlCihXLlyaefOnSpWrJi2bNmiZs2aOVwsxRHvyu/ep0gBs8M/jXF2CMgibtmc/qMaWUT+3PwRi4zh5RJfW6csx/MzMuxc1xa1y7Bz3SuXGJJUr149zZ492/7aYrHIZrNpxIgRatiwofMCAwAAQNZjycAtE3CJ3G7EiBF67LHHtGXLFsXHx+v999/X3r17FRMTo99//93Z4QEAAABZlktUGMqXL68DBw7okUce0TPPPKNr166pVatW2rRpkz755BNnhwcAAABkWS4xh8GRnTt3qkqVKkpMTEzTfsxhQEZhDgMyCnMYkFGYw4CM4spzGHK+ODPDznV1QdsMO9e9cokKAwAAAADX5MK5HQAAAJDxeKyqGRUGAAAAAA45tcLQqlWru74fGxubMYEAAAAA/0OFwcypFQYfH5+7boGBgWrTpo0zQwQAAABcysSJExUUFCQvLy/VrFlTmzZtcti3YcOGslgsybannnoq1edzaoVhxoyMW0UPAAAASA1XrjDMnz9fYWFhmjx5smrWrKlx48apWbNmioiIUP78+ZP1X7JkieLj4+2vo6OjValSJb3wwgupPidzGAAAAIBMYsyYMerYsaPatWunsmXLavLkycqePbumT5+eYv88efKo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5szRb7/9dk9BAAAAAFlReHi4fHx8TFt4eHiKfaOiopSYmKiAgABTe0BAgCIjI1Pc57ffftO0adM0derUe44xzQnD4sWL1axZM3l7e2v79u32DOjSpUv66KOP7jkQAAAAwBVk5ByGvn376tKlS6atb9++6XIdV65c0euvv66pU6fK39//no+TqnUYkvrwww81efJktWnTRvPmzbO3161bVx9++OE9BwIAAABkNZ6envL09ExVX39/f7m5uencuXOm9nPnzqlAgQLJ+h8+fFjHjh1T8+bN7W02m02SlC1bNkVERCg4OPhfz5vmCkNERITq16+frN3Hx0exsbFpPRwAAADgUiyWjNvSwsPDQ1WrVtXatWvtbTabTWvXrlXt2rWT9S9durR2796tHTt22LcWLVqoUaNG2rFjh4oUKZKq86a5wlCgQAEdOnRIQUFBpvbffvvtnmZdAwAAAEidsLAwhYaGqlq1aqpRo4bGjRuna9euqV27dpKkNm3aqHDhwgoPD5eXl5fKly9v2t/X11eSkrXfTZoTho4dO6pr166aPn26LBaLzpw5o40bN6pnz54aMGBAWg8HAAAAuBRrWr/6z0CtW7fWhQsXNHDgQEVGRiokJESrVq2yT4Q+ceKErNb0fRBqmhOGPn36yGaz6bHHHtP169dVv359eXp6qmfPnurSpUu6BgcAAADA7N1339W7776b4nvr16+/674zZ85M8/nSnDBYLBb1799fvXr10qFDh3T16lWVLVtWOXPmTPPJAQAAAFfDQmVmaU4Y7vDw8FDZsmXTMxYAAAAALibNCUOjRo1kucu4rnXr1v2ngAAAAABncuEpDE6R5oQhJCTE9DohIUE7duzQnj17FBoaml5xAQAAAHABaU4Yxo4dm2L74MGDdfXq1f8cEAAAAOBMrvyUJGdItzkdr732mqZPn55ehwMAAADgAu550vM/bdy4UV5eXul1OAAAAMApKDCYpTlhaNWqlem1YRg6e/astmzZwsJtAAAAwAMmzQmDj4+P6bXValWpUqU0dOhQNW3aNN0CAwAAAJzBSoXBJE0JQ2Jiotq1a6cKFSrIz8/vfsUEAAAAwEWkadKzm5ubmjZtqtjY2PsUDgAAAABXkuYhSeXLl9eRI0dUtGjR+xEPAAAA4FQ8VtUszY9V/fDDD9WzZ099//33Onv2rC5fvmzaAAAAADw4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cE2ePFknT550digAcF907NhR+/fv16+//ursUID/jEnPAO67zz//XNWrV1fevHn1+++/a+TIkXr33XedHRYApJtRo0apSZMmypEjh3744QfNmjVLn3/+ubPDAtIFCQOA++7gwYP68MMPFRMTo4cfflg9evRQ3759nR0WAKSbTZs2acSIEbpy5YqKFSumTz/9VB06dHB2WEC6YEgSAAAAAId4ShIAAAAAh0gYAAAAADhEwgAAAADAIRIGAAAAAA6RMAAAAABwiIQBAO5R27Zt1bJlS/vrhg0bqlu3bhkex/r162WxWBQbG+uwj8Vi0bfffpvqYw4ePFghISH/Ka5jx47JYrFox44d/+k4AADnImEA8EBp27atLBaLLBaLPDw8VLx4cQ0dOlS3bt267+desmSJhg0blqq+qfkjHwAAV8DCbQAeOI8//rhmzJihuLg4rVy5Up07d5a7u3uKi8XFx8fLw8MjXc6bJ0+edDkOAACuhAoDgAeOp6enChQooMDAQHXq1EmNGzfWd999J+nvYUTDhw9XoUKFVKpUKUnSyZMn9eKLL8rX11d58uTRM888o2PHjtmPmZiYqLCwMPn6+ipv3rx6//339c91L/85JCkuLk69e/dWkSJF5OnpqeLFi2vatGk6duyYGjVqJEny8/OTxWJR27ZtJUk2m03h4eEqWrSovL29ValSJS1atMh0npUrV6pkyZLy9vZWo0aNTHGmVu/evVWyZEllz55dxYoV04ABA5SQkJCs3xdffKEiRYooe/bsevHFF3Xp0iXT+19++aXKlCkjLy8vlS5dWp9//rnDc168eFGvvvqq8uXLJ29vb5UoUUIzZsxIc+wAgIxFhQHAA8/b21vR0dH212vXrlXu3Lm1Zs0aSVJCQoKaNWum2rVr69dff1W2bNn04Ycf6vHHH9euXbvk4eGh0aNHa+bMmZo+fbrKlCmj0aNHa+nSpXr00UcdnrdNmzbauHGjPv30U1WqVElHjx5VVFSUihQposWLF+u5555TRESEcufOLW9vb0lSeHi4vvrqK02ePFklSpTQL7/8otdee0358uVTgwYNdPLkSbVq1UqdO3fWm2++qS1btqhHjx5p/kxy5cqlmTNnqlChQtq9e7c6duyoXLly6f3337f3OXTokBYsWKDly5fr8uXLat++vd555x3NnTtXkjR37lwNHDhQn332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\n"},"metadata":{}}],"execution_count":18}]}